package com.jijuxie.message.websocket;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import jakarta.websocket.OnClose;
import jakarta.websocket.OnError;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jijuxie.common.utils.spring.ApplicationContextHolder;
import com.jijuxie.message.domain.ChatMessage;
import com.jijuxie.message.service.IChatMessageService;

import cn.dev33.satoken.stp.StpUtil;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson.JSON;

@Slf4j
@Component
@ServerEndpoint("/websocket/{userId}")
public class WebSocketServer {

    private static final Map<Long, Session> sessionMap = new ConcurrentHashMap<>();
    private Session session;
    private Long userId;
    private static ObjectMapper objectMapper;
    private IChatMessageService chatMessageService;

    @Autowired
    public void setObjectMapper(ObjectMapper objectMapper) {
        WebSocketServer.objectMapper = objectMapper;
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") Long userId) {
        log.info("用户{}连接WebSocket，会话ID：{}", userId, session.getId());

        // 验证token
        String token = session.getRequestParameterMap().get("token").get(0);
        if (token == null || token.isEmpty()) {
            sendErrorMessage(session, "未提供token");
            closeSession(session);
            return;
        }

        try {
            // 验证token的有效性
            Object loginId = StpUtil.getLoginIdByToken(token);
            if (loginId == null || !userId.toString().equals(loginId.toString())) {
                sendErrorMessage(session, "token无效或已过期");
                closeSession(session);
                return;
            }

            this.session = session;
            this.userId = userId;
            this.chatMessageService = ApplicationContextHolder.getBean(IChatMessageService.class);

            // 检查是否已有该用户的会话
            Session existingSession = sessionMap.get(userId);
            if (existingSession != null && existingSession.isOpen()) {
                try {
                    sendSystemMessage(existingSession, "您的账号在其他地方登录");
                    existingSession.close();
                    log.info("关闭用户{}的旧会话", userId);
                } catch (IOException e) {
                    log.error("关闭旧会话失败：{}", e.getMessage());
                }
            }

            sessionMap.put(userId, session);
            log.info("用户{}连接成功，当前在线人数：{}", userId, sessionMap.size());

            // 发送系统消息
            sendSystemMessage(session, "连接成功");

            // 推送未读消息
            try {
                List<ChatMessage> unreadMessages = chatMessageService.getUnreadMessages(userId);
                for (ChatMessage message : unreadMessages) {
                    String jsonMessage = objectMapper.writeValueAsString(message);
                    session.getBasicRemote().sendText(jsonMessage);
                }
            } catch (Exception e) {
                log.error("推送未读消息失败：{}", e.getMessage());
            }
        } catch (Exception e) {
            log.error("连接异常：{}", e.getMessage());
            sendErrorMessage(session, "连接异常：" + e.getMessage());
            closeSession(session);
        }
    }

    @OnClose
    public void onClose() {
        if (this.userId != null) {
            sessionMap.remove(this.userId);
            log.info("用户{}断开连接，当前在线人数：{}", this.userId, sessionMap.size());
        }
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到用户{}的消息：{}", userId, message);
        try {
            ChatMessage chatMessage = JSON.parseObject(message, ChatMessage.class);
            
            // 限制消息类型长度为10个字符
            if (chatMessage.getMessageType() != null && chatMessage.getMessageType().length() > 10) {
                chatMessage.setMessageType(chatMessage.getMessageType().substring(0, 10));
            }
            
            // 处理不同类型的消息
            if ("ping".equals(chatMessage.getMessageType())) {
                // 心跳消息，不保存到数据库，只发送响应
                
                // 发送pong响应
                ChatMessage pongMessage = new ChatMessage();
                pongMessage.setMessageType("pong");
                pongMessage.setContent("pong");
                pongMessage.setFromUserId(chatMessage.getToUserId());
                pongMessage.setToUserId(chatMessage.getFromUserId());
                pongMessage.setSendTime(LocalDateTime.now());
                pongMessage.setReadFlag("1");
                pongMessage.setDelFlag("0");
                
                sendMessageToUser(chatMessage.getFromUserId(), pongMessage);
            } else {
                // 确保所有消息都有发送时间
                if (chatMessage.getSendTime() == null) {
                    chatMessage.setSendTime(LocalDateTime.now());
                }
                chatMessage.setReadFlag("0");
                chatMessage.setDelFlag("0");
                
                // 保存并转发其他类型消息
                chatMessageService.save(chatMessage);
                
                // 实时推送消息给接收者
                if (chatMessage.getToUserId() != null && sessionMap.containsKey(chatMessage.getToUserId())) {
                    sendMessageToUser(chatMessage.getToUserId(), chatMessage);
                }
            }
        } catch (Exception e) {
            log.error("处理消息失败：", e);
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocket发生错误，会话ID：{}，错误信息：{}", session.getId(), error.getMessage());
        sendErrorMessage(session, "连接发生错误：" + error.getMessage());
    }

    public void sendMessageToUser(Long toUserId, ChatMessage message) {
        Session toSession = sessionMap.get(toUserId);
        if (toSession != null && toSession.isOpen()) {
            try {
                String jsonMessage = objectMapper.writeValueAsString(message);
                toSession.getBasicRemote().sendText(jsonMessage);
            } catch (Exception e) {
                log.error("发送消息失败：{}", e.getMessage());
            }
        }
    }

    private void sendSystemMessage(Session session, String content) {
        try {
            ChatMessage message = new ChatMessage();
            message.setFromUserId(0L);
            message.setToUserId(this.userId);
            message.setContent(content);
            message.setMessageType("system");
            message.setSendTime(LocalDateTime.now());

            String jsonMessage = objectMapper.writeValueAsString(message);
            session.getBasicRemote().sendText(jsonMessage);
        } catch (Exception e) {
            log.error("发送系统消息失败：{}", e.getMessage());
        }
    }

    private void sendErrorMessage(Session session, String content) {
        try {
            ChatMessage message = new ChatMessage();
            message.setFromUserId(0L);
            message.setToUserId(this.userId);
            message.setContent(content);
            message.setMessageType("error");
            message.setSendTime(LocalDateTime.now());

            String jsonMessage = objectMapper.writeValueAsString(message);
            session.getBasicRemote().sendText(jsonMessage);
        } catch (Exception e) {
            log.error("发送错误消息失败：{}", e.getMessage());
        }
    }

    private void closeSession(Session session) {
        try {
            session.close();
        } catch (IOException e) {
            log.error("关闭会话失败：{}", e.getMessage());
        }
    }

    /**
     * 发送系统消息给指定用户
     *
     * @param userId 用户ID
     * @param content 消息内容
     */
    public void sendSystemMessage(Long userId, String content) {
        Session session = sessionMap.get(userId);
        if (session != null && session.isOpen()) {
            sendSystemMessage(session, content);
        }
    }

    /**
     * 获取用户的未读消息
     */
    private List<ChatMessage> getUnreadMessages(Long userId) {
        // 获取最近100条消息
        Page<ChatMessage> chatHistory = chatMessageService.getChatHistory(null, userId, 1, 100);
        return chatHistory.getRecords().stream()
                .filter(message -> "0".equals(message.getReadFlag()))
                .toList();
    }
}
